package com.yfdice.android.bam;

import java.util.ArrayList;
import java.util.Set;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

import android.media.*;
import android.media.MediaPlayer.*;
import android.app.*;
import android.database.*;
import android.bluetooth.*;
import java.io.*;

import com.yfdice.android.bam.MoniterService.MoniterItem;

import android.os.Vibrator;

public class BAMService extends Service implements IBAMService  {

	private static final String TAG = "bamservice";
	public static final int s_nDefaultRSSI = 0;
	private static final int MAINNUPDATE = 0x2001;
	public  static final int MSG_TYPE_KEY_ALARM = 0x8001;
	public  static final int MSG_TYPE_BLUETOOTH_ALARM = 0x8002;
	private ServiceBinder mServiceBinder = new ServiceBinder();
	
	private BluetoothAdapter m_cwjBluetoothAdapter = null;
	private MoniterService mMoniterService = null;
	private ArrayList<MoniterItem> mMoniterList = null;
	
	private ArrayList<DeviceItem> mSearchList = new ArrayList<DeviceItem>();;
	private BluetoothDataBaseAdapter m_MyDataBaseAdapter = null;
	private int m_nMaxItemSize = 7;

	// media
	private boolean m_bIsPlaying = false;
	private MediaPlayer mMediaPlayer = null;
	private AudioManager mAudioMgr = null;
	private SharedPreferences mSettings = null;

	private NotificationManager m_NotificationMgr = null;
	private Notification m_Notification = null;
	private PendingIntent	m_PendingIntent = null;
	private Intent	m_Intent = null;
    public  boolean mCanNotification = true;
	
    private CheckMoinitorState m_thread = null;
    private boolean m_bResume = true;
    private boolean m_bRegisterReceiver = false;
    private boolean m_bDiscoveryFinish = true;
    
    private IMainOperation mMainOp = null;
    
    public class ServiceBinder extends Binder implements IBAMService{
        //@Override
        public synchronized int getMonitorCount()
        {
        	if(mMoniterList == null)
        		return 0;
 	
        	return mMoniterList.size();
        }
        
    	public synchronized MoniterItem getMonitorItem(int nIndex)
    	{
    		return mMoniterList.get(nIndex);
    	}
    	
    	public synchronized void removeMonitorItem(int nIndex)
    	{	
        	if(mMoniterList == null)
        		return;
        	
        	
    		MoniterItem item = mMoniterList.remove(nIndex);;
    		if(item != null)
    		{
    			item.stop();
    			deleteData(item.item);
    		}
    		
    	}
    	
    	public synchronized boolean addMonitorItem(DeviceItem item)
    	{
    		if (mMoniterList.size() >= m_nMaxItemSize)
    			return false;
    		
    		mMoniterService.addDevice2Moniter(item);
    		// 加入到监控列表后，删除在设备列表里面
            for(DeviceItem deviceItem: mSearchList)
            {
            	if(deviceItem.strMAC.equalsIgnoreCase(item.strMAC))
            	{
            		mSearchList.remove(deviceItem);
            		break;
            	}
            }
            
    		addData(item);
    		
    		return true;
    	}
    	
    	public int getSearchCount()
    	{
    		return mSearchList.size();
    	}
    	public DeviceItem getSearchItem(int nIndex)
    	{
    		return mSearchList.get(nIndex);
    	}
    	
    	public DeviceItem getSearchItem(String strMAC)
    	{
            for(DeviceItem deviceItem: mSearchList)
            {
            	if(deviceItem.strMAC.equalsIgnoreCase(strMAC))
            	{
            		return deviceItem;
            	}
            }
            
            return null;
    	}
    	
    	public void addData(DeviceItem item)
    	{
    		m_MyDataBaseAdapter.insertData(item.strMAC, item.strName, item.strUserName, item.nFilter);
    	}
        public void deleteData(DeviceItem item)
        {
        	m_MyDataBaseAdapter.deleteData(item.strMAC);
        }
        public void updateData(DeviceItem item)
        {
        	m_MyDataBaseAdapter.updateData(item.strMAC, item.strName, item.strUserName, item.nFilter);
        }
        
        public Handler getActivityHandler()
        {
        	return m_Mainhandler;
        }
              
        public void setMainOp(IMainOperation op)
        {
        	mMainOp = op;
        }
        
        public IMainOperation getMainOp()
        {
        	return mMainOp;
        } 
        
        public void stopService()
        {
        	Log.i(TAG, "stopService");
    		if (m_thread != null)
    			m_thread.interrupt();
    		
    		stopSelf();
        }
        public void susppendService()
        {
        	m_bResume = false;
        }
        public void resumeService()
        {
        	m_bResume = true;
        }
        public void notification(int msgType)
		{
        	if (mSettings != null)
    		{
        		boolean bNotification = mSettings.getBoolean(Settings.NOTIFICATION_NAME, true); 
        		if (false == bNotification) // 不允许则返回
        		{
        			return;
        		}
    		}
    		
        	if (m_Notification != null && m_NotificationMgr != null)
        	{
        		switch(msgType)
        		{
        		 	case MSG_TYPE_KEY_ALARM:
        		 		m_Notification.icon = R.drawable.icon;
        		 		m_Notification.flags = Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL;
        		 		m_Notification.tickerText = getString(R.string.notification_tickerText);
        		 		m_Notification.setLatestEventInfo(BAMService.this, getString(R.string.app_name), 
        		 				getString(R.string.notification_key_msg), m_PendingIntent);
        		 		m_NotificationMgr.notify(0, m_Notification);
        		 		break;

        		 	case MSG_TYPE_BLUETOOTH_ALARM:
        		 		m_Notification.icon = R.drawable.icon;
        		 		m_Notification.flags = Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL;
        		 		m_Notification.tickerText = getString(R.string.notification_tickerText);
        		 		m_Notification.setLatestEventInfo(BAMService.this, getString(R.string.app_name), 
        		 				getString(R.string.notification_bluetooth_msg), m_PendingIntent);
        		 		m_NotificationMgr.notify(1, m_Notification);  		 		
        		}
        	}
		}
        
        public void setNeedNotification()
        {
        	mCanNotification = true;
        }

    } 

    //@Override 
    public IBinder onBind(Intent intent) {
        return mServiceBinder;
    }
	
	//@Override
    public void onDestroy() {
    	super.onDestroy();
    	
		if (m_thread != null)
			m_thread.interrupt();
		
		
    	mMoniterService.stop();
    	
		if (m_bRegisterReceiver)
			unregisterReceiver(cwjReceiver);
		
		stopMediaPlayer();
		if (m_MyDataBaseAdapter != null)
			m_MyDataBaseAdapter.close();
		
		Log.v( TAG , "service on destroy " );
		stopSelf();
    }

	
    //@Override
    public void onCreate() {
        super.onCreate();
        Log.v( TAG , "service onstart " );
        initSharedPreferences();
        initData();
        initNotification();

    	m_thread = new CheckMoinitorState();
		m_thread.start();
    }

	public int getMonitorCount()
	{
		return mServiceBinder.getMonitorCount();
	}
	
	public MoniterItem getMonitorItem(int nIndex)
	{
		return mServiceBinder.getMonitorItem(nIndex);
	}
	
	public void removeMonitorItem(int nIndex)
	{
		deleteData(mServiceBinder.getMonitorItem(nIndex).item);
		mServiceBinder.removeMonitorItem(nIndex);
	}
	
	public boolean addMonitorItem(DeviceItem item)
	{
		return mServiceBinder.addMonitorItem(item);
	}
	
	public int getSearchCount()
	{
		return mServiceBinder.getSearchCount();
	}
	
	public DeviceItem getSearchItem(int nIndex)
	{
		return mServiceBinder.getSearchItem(nIndex);
	}
	
	public DeviceItem getSearchItem(String strMAC)
	{
		return mServiceBinder.getSearchItem(strMAC);
	}
	
	public void addData(DeviceItem item)
	{
		mServiceBinder.addData(item);
	}
    public void deleteData(DeviceItem item)
    {
    	mServiceBinder.deleteData(item);
    }
    public void updateData(DeviceItem item)
    {
    	mServiceBinder.updateData(item);
    }
   
    public Handler getActivityHandler()
    {
    	return mServiceBinder.getActivityHandler();
    }
      
    public void setMainOp(IMainOperation op)
    {
    	mServiceBinder.setMainOp(op);
    }
    public IMainOperation getMainOp()
    {
    	return mServiceBinder.getMainOp();
    }
    
    public void stopService()
    {
    	mServiceBinder.stopService();
    }
    public void susppendService()
    {
    	mServiceBinder.susppendService();
    }
    public void resumeService()
    {
    	mServiceBinder.resumeService();
    }
    
    private void recoverData()
    {
    	m_MyDataBaseAdapter = new BluetoothDataBaseAdapter(this);
    	m_MyDataBaseAdapter.open();
    	
    	Cursor cur = m_MyDataBaseAdapter.fetchAllData();
    	if (cur == null)
    		return;
    		
		if (cur.moveToFirst())
		{
			do
			{
				DeviceItem item = new DeviceItem();
				int nIndex = cur.getColumnIndex(BluetoothDataBaseAdapter.KEY_MAC);
				item.strMAC = cur.getString(nIndex);
				
				nIndex = cur.getColumnIndex(BluetoothDataBaseAdapter.KEY_NAME);
				item.strName = cur.getString(nIndex);
				
				nIndex = cur.getColumnIndex(BluetoothDataBaseAdapter.KEY_USERNAME);
				item.strUserName = cur.getString(nIndex);
				
				nIndex = cur.getColumnIndex(BluetoothDataBaseAdapter.KEY_FILTER);
				item.nFilter = cur.getInt(nIndex);
				mMoniterService.addDevice2Moniter(item);
			} while (cur.moveToNext());
		}
    }
    
    private synchronized void initData()
    {
        m_cwjBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mMoniterService = MoniterService.getInstance();      
        recoverData();	
        mMoniterList = mMoniterService.getMoniterList();
        mMoniterService.start();
        
    	int warningRSSI = mSettings.getInt(Settings.RSSI_NAME, 80);
    	MoniterService.getInstance().setWarningRSSI(warningRSSI);
    	int schedule = mSettings.getInt(Settings.SEARCHTIME_NAME, 1000);
    	MoniterService.getInstance().setScanSchedule(schedule);
    }
    
    public void notification(int msgType)
    {
    	mServiceBinder.notification(msgType);
    }
    
    public void setNeedNotification()
    {
    	mServiceBinder.setNeedNotification();
    }
    
    private void initNotification()
    {
    	m_Intent = new Intent(BAMService.this, BurglarAlarmMonitor.class);
    	Bundle bundle = new Bundle();
    	bundle.putString("NotificationKey", "notification");
    	m_Intent.putExtras(bundle);
    	m_Intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
				| Intent.FLAG_ACTIVITY_NEW_TASK);
    	m_PendingIntent = PendingIntent.getActivity(BAMService.this, 0, m_Intent, PendingIntent.FLAG_UPDATE_CURRENT);
    	m_Notification = new Notification();
    	m_NotificationMgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    }
    
    private void initSharedPreferences()
    {
    	mSettings = getSharedPreferences(Settings.PREFS_NAME, 0);
    }
    
    private final BroadcastReceiver cwjReceiver = new BroadcastReceiver() 
	{ 
	    public void onReceive(Context context, Intent intent) 
	    { 
	        String action = intent.getAction(); 
	        if (BluetoothDevice.ACTION_FOUND.equals(action)) 
	        { 
	             BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 
	             //device.getBondState()
	             Log.i(TAG, "Receive Action_Found");
	             if (device != null && device.getBondState() != BluetoothDevice.BOND_BONDED) 
	             {
	            	 String strMacAddress = device.getAddress();
	            	 
	            	 // 如果已经存在监控列表里面，不加入
	            	 if(mMoniterService.isInMoniterList(strMacAddress))
	            		 return;
	            	 
	            	 int nRSSI = Math.abs(intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, (short)0));	            	 
	            	 DeviceItem item = (DeviceItem)getSearchItem(strMacAddress);
	            	 
	            	 if (item != null) // find and update
	            	 {          		 
	            		 item.nRSSI = nRSSI;
	            		 if (device.getName().length() > 0)
	            			 item.strName = device.getName();
	            	 }
	            	 else
	            	 {
	            		 Log.i(TAG, "found new device.");
	            		 item = new DeviceItem();
	            		 if (device.getName().length() <= 0)
	            		 {
	            			 item.strName = getString(R.string.unknown_device);
	            		 }
	            		 else
	            			 item.strName = device.getName();
	            		 
	            		 item.nRSSI = nRSSI;
	            		 item.strMAC = strMacAddress;
	            		 item.nFilter = DeviceItem.FilterType_None;
	            		 mSearchList.add(item);
	            	 }
	             }
	             
	        } 
	        else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
	        {
	        	Log.d(TAG, "Receive Discovery_Finished");
	        	Set<BluetoothDevice> pairedDevices = m_cwjBluetoothAdapter.getBondedDevices(); 

	        	if (pairedDevices.size() > 0)
	        	{ 
	        	    for (BluetoothDevice device : pairedDevices) 
	        	    { 
	        	    	Log.i(TAG, "pairedDevices name = " + device.getName());
	        	    } 
	        	}
	        	
	        	m_bDiscoveryFinish = true;
	        }
	    } 
	}; 
	
	private void startDiscovery(boolean bFirst)
	{
		Log.d(TAG, "begin startDiscovery.");
    	m_cwjBluetoothAdapter.startDiscovery();
    	m_bDiscoveryFinish = false;
    	
    	mSearchList.clear();
        // Get the local Bluetooth adapter
    	BluetoothAdapter BtAdapter = BluetoothAdapter.getDefaultAdapter();

        // Get a set of currently paired devices
        Set<BluetoothDevice> pairedDevices = BtAdapter.getBondedDevices();

        // If there are paired devices, add each one to the ArrayAdapter
        if (pairedDevices.size() > 0) 
        {
            for (BluetoothDevice device : pairedDevices) {
           	 String strMacAddress = device.getAddress();
        	 
        	 // 如果已经存在监控列表里面，不加入
        	 if(mMoniterService.isInMoniterList(strMacAddress))
        		 continue;
        	 
        	 short nRSSI = 0;	            	 
        	 DeviceItem item = (DeviceItem)getSearchItem(strMacAddress);
        	 
        	 if (item != null) // find and update
        	 {          		 
        		 item.nRSSI = nRSSI;
        		 if (device.getName().length() > 0)
        			 item.strName = device.getName();
        	 }
        	 else
        	 {
        		 Log.i(TAG, "found new device.");
        		 item = new DeviceItem();
        		 if (device.getName().length() <= 0)
        		 {
        			 item.strName = getString(R.string.unknown_device);
        		 }
        		 else
        			 item.strName = device.getName();
        		 
        		 item.nRSSI = nRSSI;
        		 item.strMAC = strMacAddress;
        		 item.nFilter = DeviceItem.FilterType_None;
        		 mSearchList.add(item);
        	 }
            }
        }
            
    	if (bFirst)
    	{
	    	if (m_bRegisterReceiver) //  ∑¿÷π÷ÿΩ¯»Î
	    		unregisterReceiver(cwjReceiver);
	    	
	    	IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); 
	    	registerReceiver(cwjReceiver, filter);
	    	
	    	filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
	    	registerReceiver(cwjReceiver, filter);
	    	
	    	m_bRegisterReceiver = true;
    	}
	}
   
	public Handler m_Mainhandler = new Handler() {
		// @Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case IBAMService.s_msgEnableBluetooth:
				startDiscovery(true);
				break;
			}
			super.handleMessage(msg);
		}
	};

    private void stopMediaPlayer()
    {
    	if (mMediaPlayer != null)
    	{
    		mMediaPlayer.stop();
    		mMediaPlayer.release();
    	}
    }
    
    private class CheckMoinitorState extends Thread
	{
		public void run()
		{
			Log.d(TAG, "thread start.");
			
			super.run();
            try 
            {
            	do 
                {
                	Log.d(TAG, "CheckMoinitorState thread run begin...");
                	
                	// 定时轮询是否key在线
        			Message message = new Message();
        			message.what = BAMService.MAINNUPDATE;
        			m_updatehandler.sendMessage(message);
        			
                	Thread.sleep(1000);
                           		
                	Log.d(TAG, "CheckMoinitorState thread continue...");
                } while (!CheckMoinitorState.interrupted());
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
		}
	}
    
	private Handler m_updatehandler = new Handler() {
		// @Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			switch (msg.what) {
			case BAMService.MAINNUPDATE:
				Log.i(TAG, "MAINNUPDATE");
				updateItems();
				break;
			}
			super.handleMessage(msg);
		}
	};
	
	private void makesureBlueboothenable()
	{		
		if (BluetoothAdapter.getDefaultAdapter().isEnabled()) 
		{	
			mCanNotification = true;
			return;
		}
		else if(!mCanNotification)
		{
			return;
		}
		else
		{
			mCanNotification = false;
			notification(MSG_TYPE_BLUETOOTH_ALARM);
		}
	}
    
    private void updateItems()
    {	
		// 保证蓝牙开启，不开启就发notification通知
		makesureBlueboothenable();
		
    	//Log.d(TAG, "updateItems begin.");
    	boolean bShouldAlarm = false;
    	if(mCanNotification)
	    { 
    		if(mMoniterService.hasDisconnectDevice() || mMoniterService.hasLowSingalDevice())
    		{
    			// 查询当前链接情况，如有断开而且是在监控范围内则报警
    			bShouldAlarm = true;    			
    		}
	    }
    	
    	notifyAlarm(bShouldAlarm);	
    	if (mMoniterService.hasDisconnectDevice() || mMoniterService.hasLowSingalDevice())
    		notification(MSG_TYPE_KEY_ALARM);
    }
    
    public void notifyAlarm(boolean bShouldAlarm)
    {
    	if (bShouldAlarm)
    	{
    		try
	    	{
    			// 先判断一下音量是否打开�
    			if (isSilent())
    			{
    				onVibrator();
    			}
    			else if (!m_bIsPlaying)
	    		{
	    			m_bIsPlaying = true;
	    			if (mMediaPlayer == null)
	    			{
	    				mMediaPlayer = MediaPlayer.create(BAMService.this, R.raw.alarm);
	    				mMediaPlayer.setLooping(true);
		    			try
		    			{
		    				mMediaPlayer.prepare();
		    			}
		    			catch (IllegalStateException e)
		    			{
		    				e.printStackTrace();
		    			}
		    			catch (IOException e)
		    			{
		    				e.printStackTrace();
		    			}
	    			}
	    			
	    			mMediaPlayer.start();
	    			//onNotification();
	    		}
	    	}
	    	catch (IllegalStateException e)
	    	{
	    		e.printStackTrace();
	    	}
	    	
	    	if (mMediaPlayer != null)
	    	{
	    		mMediaPlayer.setOnCompletionListener(new OnCompletionListener()
	    		{
	    			public void onCompletion(MediaPlayer arg0)
	    			{
	    				mMediaPlayer.release();
	    			}
	    		});
	    	}
    	}
    	else // ‘›Õ�
    	{
    		if (mMediaPlayer != null)
    		{
    			m_bIsPlaying = false;
    			mMediaPlayer.pause();
    		}
    	}
    }
    
    private boolean isSilent()
    {
    	// 先判断媒体声音是否有，若无，怎振�
    	// 若有，再判断设置项是否允�
    	if (mAudioMgr == null)
		{
			mAudioMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
		}
    	
    	if (mAudioMgr == null)
    		return false;
    	
		int nMusic = mAudioMgr.getStreamVolume(AudioManager.STREAM_MUSIC);
		if (nMusic <= 0)
			return true;
		
		if (mSettings == null)
			return false;
		
		boolean bSilenceAlarm = mSettings.getBoolean(Settings.SILENCE_NAME, true); 
		if (false == bSilenceAlarm) // 此时若静音，是不允许报警�
		{
			 // 判断是否为静�
			int nVolumn = mAudioMgr.getStreamVolume(AudioManager.STREAM_RING);
			if (nVolumn <= 0)
				return true;
		}
		 
		return false;
    }
    
    private void onVibrator()
    {
    	// 静音前把之前的播放停�
		if (m_bIsPlaying == true && mMediaPlayer != null)
		{
			m_bIsPlaying = false;
			mMediaPlayer.pause();
		}
		
    	Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
		if (vibrator != null)
			vibrator.vibrate(new long[]{10, 100, 20, 200}, -1);  
    }
}
